# api/app/main.py
from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException
from sqlalchemy import func
from sqlalchemy.orm import Session
import os
import uuid
import shutil
from . import models

from celery import Celery

CELERY_BROKER_URL = os.getenv("CELERY_BROKER_URL", "redis://redis:6379/0")
celery_app = Celery("api_tasks", broker=CELERY_BROKER_URL)

app = FastAPI(title="农业大模型评测系统 API")


@app.on_event("startup")
def on_startup():
    models.create_tables()


def get_db():
    db = models.SessionLocal()
    try:
        yield db
    finally:
        db.close()


@app.get("/")
def read_root():
    return {"message": "评测系统 API 运行正常!"}


@app.post("/submit", status_code=202)
def submit_solution(
        team_id: str = Form(...),
        file: UploadFile = File(...),
        db: Session = Depends(get_db)
):
    # 1. 为本次提交生成一个唯一的ID (UUID)
    submission_id = str(uuid.uuid4())

    # 2. 定义文件保存路径
    # 我们先临时保存在 docker-compose.yml 中挂载的 submissions_temp 卷里
    file_location = f"/submissions_temp/{submission_id}.zip"

    # 3. 保存上传的 zip 文件
    try:
        with open(file_location, "wb+") as file_object:
            shutil.copyfileobj(file.file, file_object)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"无法保存文件: {e}")
    finally:
        file.file.close()

    # 4. 在数据库中创建一条新的提交记录
    new_submission = models.Submission(
        id=submission_id,
        team_id=team_id,
        status=models.SubmissionStatus.PENDING,
        zip_file_path=file_location
    )
    db.add(new_submission)
    db.commit()
    db.refresh(new_submission)

    celery_app.send_task("worker.run_evaluation", args=[submission_id])

    return {
        "message": "提交成功，正在排队等待评测...",
        "submission_id": submission_id,
        "team_id": team_id
    }

@app.get("/status/{submission_id}")
def get_submission_status(submission_id: str, db: Session = Depends(get_db)):
    """根据提交ID查询评测状态和结果"""
    submission = db.query(models.Submission).filter(models.Submission.id == submission_id).first()
    if not submission:
        raise HTTPException(status_code=404, detail="Submission not found")
    return submission

@app.get("/leaderboard")
def get_leaderboard(db: Session = Depends(get_db)):
    subquery = db.query(
        models.Submission.team_id,
        func.max(models.Submission.total_score).label("max_score")
    ).filter(
        models.Submission.status == models.SubmissionStatus.COMPLETED
    ).group_by(models.Submission.team_id).subquery()

    leaderboard_data = db.query(models.Submission).join(
        subquery,
        (models.Submission.team_id == subquery.c.team_id) &
        (models.Submission.total_score == subquery.c.max_score)
    ).order_by(models.Submission.total_score.desc()).all()

    return leaderboard_data